<?php
/**
 * @author jonathan <jo.link.noir@gmail.com>
 * @version 1.0: jo_link_noir
 * @date 07-01-2010
 */
class U1_DAO_User extends SW_DAO
{
	/** @var array : {id => SW_Player, ...}*/
	static private $player = array();


	/**
	 * Créé un joueur et utilise deleteWaiting()
	 * @param StdClass|string|int $user : objet qui comporte {[id], pseudo, password, race, mail, ref_alliance} ou mail ou id
	 * @param string $password = null : si null et que $user n'est pas un objet alors $user est l'id du joueur
	 * @return SW_Player|null
	 */
	static public function create($u, $password = null)
	{
		if (!is_object($u) && null === ($u = self::selectInfoCreate($u, $password)))
			return null;

		if (!self::$db->exec('INSERT INTO user(pseudo, password, race, mail, ref_alliance, date_connect) VALUES('
			.self::$db->quote($u->pseudo).','
			.self::$db->quote($u->password).','
			.self::$db->quote($u->race).','
			.self::$db->quote($u->mail).','
			.((int)$u->ref_alliance).',NOW())'
		))
			return null;

		$user_id = self::$db->lastInsertId();
		/// TODO valeur à prendre aléatoirement dans la table galaxie (et ajouter unique pour g+s+p)
		if (!self::$db->exec('UPDATE planet SET ref_user='.$user_id.' WHERE ref_user=0 LIMIT 1'))
		{
			self::delete($user_id);
			return null;
		}

		self::deleteWaiting(isset($u->id) ? $u->id : 0);

		$u->id = (int)$user_id;
		return self::newPlayer($u);
	}

	/**
	 * @param int $id
	 * @return SW_Player|null
	 */
	static public function select($id)
	{
		if (isset(self::$player[$id]))
			return self::$player[$id];

		if (false === isset(self::$queries[__METHOD__]))
		{
			self::$queries[__METHOD__] = self::$db->prepare(
				'SELECT pseudo, race, ref_alliance FROM user WHERE id=?'
			);
		}

		self::$queries[__METHOD__]->execute(array((int)$id));
		if ($u = self::$queries[__METHOD__]->fetchObject())
		{
			$u->id = $id;
			return self::newPlayer($u);
		}
		else
			return self::$player[(int)$id] = null;
	}

	/**
	 * @param string $mail
	 * @param string $password
	 * @return SW_Player|null : {id, pseudo, race, ref_alliance, sid, SW_Player}
	 */
	static public function selectConnect($mail, $password)
	{
		$u = self::$db->query('SELECT id, race, pseudo, ref_alliance, sid FROM user WHERE mail='.self::$db->quote($mail).' AND password="'.self::hashPass($password).'"')
			->fetchObject();
		if (!$u)
			return null;

		self::newPlayer($u);
		return $u;
	}

	static private function newPlayer(StdClass $u)
	{
		$id = (int)$u->id;
		return self::$player[$id] = $u->player = U1_Player::factory($id, $u->race, $u->pseudo, $u->ref_alliance);
	}

	/**
	 * @param SW_Player $player
	 * @param string $sid : id de la session
	 * @return int : nombre de lignes affectées
	 */
	static public function connect(SW_Player $player, $sid)
	{
		return self::$db->exec('UPDATE user SET date_connect=NOW(), sid="'.$sid.'" WHERE id='.$player->getId());
	}

	/**
	 * @param string $password
	 * @return string [32] : md5('bidule_39'.$password.'_')
	 */
	static public function hashPass($password)
	{
		return md5('bidule_39'.$password.'_');
	}

	/**
	 * Ajoute un joueur dans la table s'attente et retourne son id d'enregistrement
	 * @param string $pseudo
	 * @param string $password
	 * @param string $race
	 * @param string $mail
	 * @return int
	 * @exception SW_DAO_Exception
		1 : Le pseudo est déjà utiliser
		2 : L'adresse mail est déjà utiliser
		3 : Un compte sous le même pseudo attend d'être valider
		4 : Un compte avec la même adresse mail attend d'être valider
	 */
	static public function insert($pseudo, $password, $race, $mail)
	{
		$q_mail = self::$db->quote($mail);
		$q_pseudo = self::$db->quote($pseudo);

		//déjà présent dans la table user
		$u = self::$db->query('SELECT pseudo, mail FROM user WHERE mail='.$q_mail.' OR pseudo='.$q_pseudo)
			->fetchObject();
		if ($u)
		{
			if ($u->pseudo === $pseudo)
				throw new SW_DAO_Exception('Le pseudo est déjà utiliser', 1);
			else
				throw new SW_DAO_Exception('L\'adresse mail est déjà utiliser', 2);
		}

		//déjà présent dans la table user_waiting
		$u = self::$db->query('SELECT pseudo, mail FROM user_waiting WHERE mail='.$q_mail.' OR pseudo='.$q_pseudo)
			->fetchObject();
		if ($u)
		{
			if ($u->pseudo === $pseudo)
				throw new SW_DAO_Exception('Un compte sous le même pseudo attend d\'être valider', 3);
			else
				throw new SW_DAO_Exception('Un compte avec la même adresse mail attend d\'être valider', 4);
		}

		self::$db->exec('INSERT INTO user_waiting(pseudo, password, race, mail, date) VALUES('
			.$q_pseudo.','
			.'"'.self::hashPass($password).'",'
			.((int)$race).','
			.$q_mail.','
			.'NOW())'
		);

		return (int)self::$db->lastInsertId();
	}

	/**
	 * Supprime le joueur pointer par son id et tout enregistrement datant de plus de 30 jouurs
	 * @param int $id_user
	 * @return int : nombre d'enregistrement effacé
	 */
	static public function deleteWaiting($id)
	{
		return  self::$db->exec('DELETE FROM user_waiting WHERE date < date - INTERVAL 30 DAY OR id='.((int)$id));
	}

	/**
	 * @param int $id_user
	 * @return int : nombre d'enregistrement effacé
	 */
	static public function delete($id_user)
	{
		return  self::$db->exec('DELETE FROM user WHERE id='.((int)$id_user));
	}

	/**
	 * @param int $ref_alliance
	 * @return array : {SW_Player:{id, pseudo, int:race, ref_alliance}}
	 */
	static public function selectInAlliance($ref_alliance)
	{
		if (false === isset(self::$queries[__METHOD__]))
		{
			self::$queries[__METHOD__] = self::$db->prepare(
				'SELECT id, pseudo, race, ref_alliance FROM user WHERE ref_alliance=?'
			);
		}

		$sth = self::$queries[__METHOD__]->execute(array($ref_alliance));
		$users = array();

		while($u = $sth->fetchObject())
			$users[] = U1_Player::factory((int)$u->id, (int)$u->race, $u->pseudo);
		return $users;
	}

	/**
	 * @param string|int $mail : adresse mail ou id
	 * @param string $password = null : si null alors $mail est l'id du joueur
	 * @return stdObject|null : {id, ref_alliance, pseudo, password, race, mail}
	 */
	static public function selectInfoCreate($mail, $password = null)
	{
		$result = self::$db->query('SELECT id, pseudo, password, race, mail FROM user_waiting WHERE '.((null === $password) ? 'id='.((int)$mail) : 'mail='.self::$db->quote($mail).' AND password="'.self::hashPass($password).'"'))->fetchObject();

		if (!$result)
			return null;

		$result->ref_alliance = 0;
		return $result;
	}
}